package com.kevin.v2.spring.formework.context.support;

import com.kevin.v2.spring.formework.beans.config.KvBeanDefinition;
import com.kevin.v2.spring.formework.context.KvApplicationContext;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 加载配置文件类
 */
public class KvBeanDefinitionReader  {

   private Properties properties = new Properties();

   //存储扫描的包下的类名 及包名
   private Map<String, String> registerBeanName = new HashMap<String, String>();

   private static final String SCAN_PACKAGE = "scanPackage";


   public KvBeanDefinitionReader (String... locations) throws IOException {
      //定位配置文件
      loadServletConfig(locations[0]);
      //扫描需要管理的bean
      scanPackage();

   }

   /**
    * 加载配置文件解析成每个beandefinition
    *
    * @return
    * @throws Exception
    */
   public List<KvBeanDefinition> loadBeanDefinitions () throws Exception {
      List<KvBeanDefinition> beanDefinitions = new ArrayList<>();
      for (Map.Entry<String, String> beanName : registerBeanName.entrySet()) {
         Class<?> clazz = Class.forName(beanName.getKey());
         if (clazz.isInterface()) continue;
         KvBeanDefinition beanDefinition = new KvBeanDefinition();
         beanDefinition.setBeanClassName(clazz.getName());
         beanDefinition.setFactoryName(beanNametoLowerCase(clazz.getSimpleName()));
         beanDefinitions.add(beanDefinition);
      }
      return beanDefinitions;
   }

   /**
    * 加载配置文件
    * @param classpath
    * @throws IOException
    */
   private void loadServletConfig (String classpath){

      //通过类的 类加载器加载配置文件
      InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(classpath.replaceAll("classpath:",""));
      try {
         properties.load(resourceAsStream);
      } catch (IOException e) {
         e.printStackTrace();
      }finally {
         try {
            resourceAsStream.close();
         } catch (IOException e) {
            e.printStackTrace();
         }

      }
   }

   /**
    * 扫描 配置文件 scanPackage 下的包 将所有beanPath路径保存起来
    */
   private void scanPackage () {
      doScanner( properties.getProperty(SCAN_PACKAGE));
   }

   /**
    * 扫描 配置文件 scanPackage 下的包 将所有beanPath路径保存起来
    *
    * @param scanPackage
    */
   private void doScanner (String scanPackage) {
      String url = this.getClass().getClassLoader().getResource(scanPackage.replaceAll("\\.", "/")).getFile();
      File file = new File(url);
      for (File file1 : file.listFiles()) {
         if (file1.isDirectory()) {
            url = scanPackage + "." + file1.getName();
            doScanner(url);
         } else {
            if (!file1.getName().endsWith("class")) continue;
            String beanPath = scanPackage + "." + file1.getName().substring(0, file1.getName().lastIndexOf("."));

            registerBeanName.put(beanPath, null);

         }
      }
   }


   /**
    * 将beanName
    * 首字符小写作为ioc容器里的 key
    *
    * @param simpleName
    * @return
    */
   String beanNametoLowerCase (String simpleName) {
      char[] car = simpleName.toCharArray();
      //首字符+32转小写
      //首字母-32转大写
      car[0] += 32;
      return String.valueOf(car);
   }

   public Properties getProperties () {
      return properties;
   }
}
